package im.starchat.chat.rest;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;

import java.io.IOException;
import java.util.List;

import im.starchat.chat.XLApplication;
import im.starchat.chat.rest.model.AccountBean;
import im.starchat.chat.rest.model.BatchCancelRequestBody;
import im.starchat.chat.rest.model.ChannelBean;
import im.starchat.chat.rest.model.CommentBean;
import im.starchat.chat.rest.model.ContributionBean;
import im.starchat.chat.rest.model.GiftBean;
import im.starchat.chat.rest.model.MsgBean;
import im.starchat.chat.rest.model.PreviewBean;
import im.starchat.chat.rest.model.RoomBean;
import im.starchat.chat.rest.model.UserBean;
import im.starchat.chat.rest.model.WeixinUserBean;
import im.starchat.chat.rest.model.api.CheckVersionResponse;
import im.starchat.chat.rest.model.api.ConfigResponse;
import im.starchat.chat.rest.model.api.LoginResponse;
import im.starchat.chat.rest.model.api.NullResponse;
import im.starchat.chat.rest.model.api.PreviewResponse;
import im.starchat.chat.rest.model.api.UpTokenResponse;
import im.starchat.chat.rest.model.api.UserSettingResponse;
import im.starchat.chat.utils.PreferencesStorageUtil;
import retrofit.Callback;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.client.OkClient;
import retrofit.converter.GsonConverter;
import retrofit.http.Body;
import retrofit.http.DELETE;
import retrofit.http.GET;
import retrofit.http.Multipart;
import retrofit.http.POST;
import retrofit.http.PUT;
import retrofit.http.Part;
import retrofit.http.Path;
import retrofit.http.Query;

/**
 * Created by skyfishjy on 12/18/14.
 */
public class RestClient {

    public static final int DEFAULT_PAGE = 1;
    public static final int DEFAULT_PREPAGE = 20;
    //正式环境
    public static final String BASE_DOMAIN = "http://xingliao.dalongkeji.com/";
    //测试环境
    public static final String BASE_DOMAIN_TEST = "http://starschats.dalongkeji.com/";

    private static String BASE_XL_URL = BASE_DOMAIN + "api/v1/";

    static{
        if(!PreferencesStorageUtil.isUseOfficialUrl(XLApplication.getInstance())){
            BASE_XL_URL = BASE_DOMAIN_TEST + "api/v1/";
        }else{
            BASE_XL_URL = BASE_DOMAIN + "api/v1/";
        }
    }

    public static final String BASE_IMG_URL = "http://7xrqoy.com1.z0.glb.clouddn.com/";
    public static final String BASE_UM_URL = "https://api.weixin.qq.com/sns/";
    private XLService xlService;
    private UmService umService;

    public RestClient(String accessToken, String version) {
        Gson gson = new GsonBuilder()
                .registerTypeAdapterFactory(new ItemTypeAdapterFactory())
                .create();
        OkClient okClient = new OkClient();
        RestAdapter xlRestAdapter = new RestAdapter.Builder()
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setEndpoint(BASE_XL_URL)
                .setConverter(new GsonConverter(gson))
                .setRequestInterceptor(new XLRequestInterceptor(accessToken, version))//设置拦截
                .setClient(okClient)
                .build();
        RestAdapter umRestAdapter = new RestAdapter.Builder()
                .setLogLevel(RestAdapter.LogLevel.FULL)
                .setEndpoint(BASE_UM_URL)
                .setConverter(new GsonConverter(gson))
                .setRequestInterceptor(new XLRequestInterceptor(accessToken, version))
                .setClient(okClient)
                .build();

        xlService = xlRestAdapter.create(XLService.class);
        umService = umRestAdapter.create(UmService.class);
    }


    public RestClient() {
        this(null, null);
    }

    public void signIn(String provider, String uid,String access_token,
                       String refresh_token,String expired_at,String avatar,
                       String gender, String city,String nickname,String description,
                       Callback<LoginResponse> callback) {
        xlService.signIn(provider, uid, access_token,
                refresh_token, expired_at, avatar,
                gender, city, nickname, description, callback);
    }

    public void getWeiXinUserInfo(String access_token, String openid, Callback<WeixinUserBean> callback){
        umService.getUserInfo(access_token, openid, callback);
    }

    public void getPreviews(int page, int per_page, Callback<PreviewBean[]> callback){
        xlService.getPreviews(page, per_page, callback);
    }

    public void getUserPreviews(String id, int page, int per_page, Callback<PreviewBean[]> callback){
        xlService.getUserPreviews(id, page, per_page, callback);
    }

    public void getFeedList(String type, int page, int per_page, Callback<List<RoomBean>> callback){
        xlService.getFeedList(type, page, per_page, callback);
    }

    public void getStars(String type, int page, int per_page, Callback<ChannelBean[]> callback){
        xlService.getStars(type, page, per_page, callback);
    }

    public void getNotices(int page, int per_page, Callback<MsgBean[]> callback){
        xlService.getNotices(page, per_page, callback);
    }

    public void getUserInfo(String id, Callback<UserBean> callback){
        xlService.getUserInfo(id, callback);
    }

    public void getContributions(String id, int page, int per_page, Callback<ContributionBean[]> callback){
        xlService.getContributions(id, page, per_page, callback);
    }

    public void putUserInfo( String id, String nickname, String gender,
                             String description, String avatar,
                             String address, Callback<UserBean> callback){
        xlService.putUserInfo(id, nickname, gender, description, avatar, address, callback);
    }

    public void putUserInfoNickName(String id, String nickname, Callback<UserBean> callback){
        xlService.putUserInfoNickName(id, nickname, callback);
    }

    public void putUserInfoGender( String id, String gender, Callback<UserBean> callback){
        xlService.putUserInfoGender(id, gender, callback);
    }

    public void putUserInfoDescription( String id, String description, Callback<UserBean> callback){
        xlService.putUserInfoDescription(id, description, callback);
    }

    public void putUserInfoAvatar( String id, String avatar, Callback<UserBean> callback){
        xlService.putUserInfoAvatar(id, avatar, callback);
    }

    public void putUserInfoAddress( String id, String address, Callback<UserBean> callback){
        xlService.putUserInfoAddress(id, address, callback);
    }

    public void enterRoom(String id,String name, Callback<NullResponse> callback){
        xlService.enterRoom(id, name, callback);
    }

    public void exitRoom(String id, Callback<NullResponse> callback){
        xlService.exitRoom(id, callback);
    }

    //获取房间用户
    public void getRoomUsers(String id,String eq, Callback<UserBean[]> callback){
        xlService.getRoomUsers(id, eq, callback);
    }

    public void getRoomComments(@Path("id") String id, Callback<CommentBean[]> callback){
        xlService.getRoomComments(id, callback);
    }

    public void apply(String invite_code, Callback<NullResponse> callback){
        xlService.apply(invite_code, callback);
    }

    public void getFollowers(String id, int page, int per_page, Callback<UserBean[]> callback){
        xlService.getFollowers(id, page, per_page, callback);
    }

    public void following(String id, String name, Callback<NullResponse> callback){
        xlService.following(id, name, callback);
    }

    public void delFollowing(String id, Callback<NullResponse> callback){
        xlService.delFollowing(id, callback);
    }

    public void appointments(String preview_id, Callback<PreviewResponse> callback){
        xlService.appointments(preview_id, callback);
    }

    public void delAppointments(String preview_id, Callback<PreviewResponse> callback){
        xlService.delAppointments(preview_id, callback);
    }

    public void getAppointments(String preview_id, int page, int per_page, Callback<PreviewBean[]> callback){
        xlService.getAppointments(preview_id, page, per_page, callback);
    }

    //上传图片
    public void upToken(String key, Callback<UpTokenResponse> callback){
        xlService.upToken(key, callback);
    }

    public void postPreviews(String name, String start_at, String cover, Callback<PreviewBean> callback){
        xlService.postPreviews(name, start_at, cover, callback);
    }

    public void putFeedInfo(String id, String name, String description, String cover, int duration,
                            String end_at, String tencent_group_id,
                            String tencent_file_id, String status, Callback<RoomBean> callback){
        xlService.putFeedInfo(id, name, description, cover, duration, end_at, tencent_group_id, tencent_file_id, status, callback);
    }

    public void getGifts( Callback<GiftBean[]> callback){
        xlService.getGifts(callback);
    }

    public void putFeedInfo(String id, int duration, String end_at, String tencent_file_id, String status, Callback<RoomBean> callback){
        xlService.putFeedInfo(id, duration, end_at, tencent_file_id, status, callback);
    }

    public void putFeedInfo(String id, String status, Callback<RoomBean> callback){
        xlService.putFeedInfo(id, status, callback);
    }

    public void putFeedInfo(String id, String tencent_channel_id, String tencent_channel_url, Callback<RoomBean> callback){
        xlService.putFeedInfo(id, tencent_channel_id, tencent_channel_url, "online", callback);
    }

    //获取直播列表
    public void postZhibo(String name, String cover, String tencent_room_id, Callback<RoomBean> callback){
        xlService.postZhibo(name, cover, tencent_room_id, callback);
    }

    public void getFeedInfo(String id, Callback<RoomBean> callback){
        xlService.getFeedInfo(id, callback);
    }

    public void postPraises(String id, Callback<NullResponse> callback){
        xlService.postPraises(id, "online", callback);
    }

    //第一期每次发布一个礼物
    public void sendGift(String id, String gift_id, Callback<NullResponse> callback){
        xlService.sendGift(id, gift_id, "1", callback);
    }

    //发送弹幕和评论在一起
    public void sendRoomComments(String id, String message, boolean is_barrage, Callback<NullResponse> callback){
        xlService.sendRoomComments(id, message, is_barrage, callback);
    }

    //检查版本升级
    public void checkVersion(Callback<CheckVersionResponse> callback){
        xlService.checkVersion(callback);
    }

    //获取用户配置
    public void getConfig( Callback<ConfigResponse> callback){
        xlService.getConfig(callback);
    }

    public void getSetting( Callback<UserSettingResponse> callback){
        xlService.getSetting(callback);
    }

    public void putSetting(boolean follow_notice,boolean system_msg_notice, Callback<UserSettingResponse> callback){
        xlService.putSetting(follow_notice, system_msg_notice, callback);
    }

    public void postHeartClick(String id, Callback<NullResponse> callback){
        xlService.postHeartClick(id, "online", callback);
    }

    public void putMobileDevice(String type, String device_token, Callback<NullResponse> callback){
        xlService.putMobileDevice(type, device_token, callback);
    }

    public void getUserRooms(String id, int page, int per_page, Callback<RoomBean[]> callback){
        xlService.getUserRooms(id, page, per_page, callback);
    }

    public void getAccountInfo( Callback<AccountBean> callback){
        xlService.getAccountInfo(callback);
    }

    public void withDraw(String amount, Callback<NullResponse> callback){
        xlService.withDraw(amount, callback);
    }

    public void pay( String product_id, String channel, int amount, float price, Callback<NullResponse> callback){
        xlService.pay(product_id, channel, amount, price, callback);
    }

    public void getFollowings(String id, int page, int per_page, Callback<UserBean[]> callback){
        xlService.getFollowings(id, page, per_page, callback);
    }

//    public void bratchFollowing(String user_ids, Callback<NullResponse> callback){
//        xlService.bratchFollowing(user_ids, callback);
//    }
//
//    public void bratchCancelFollowing(String user_ids, Callback<NullResponse> callback){
//        xlService.bratchCancelFollowing(user_ids, callback);
//    }

    public void bratchFollowing(BatchCancelRequestBody br, Callback<NullResponse> callback){
        xlService.bratchFollowing(br, callback);
    }

    public void bratchCancelFollowing(BatchCancelRequestBody br, Callback<NullResponse> callback){
        xlService.bratchCancelFollowing(br, callback);
    }

    public void bindWeixin(String open_id, Callback<NullResponse> callback){
        xlService.bindWeixin(open_id, callback);
    }

    interface UmService {
        //获取微信用户信息
        @GET("/userinfo")
        public void getUserInfo(@Query("access_token") String access_token, @Query("openid") String openid, Callback<WeixinUserBean> callback);
    }

    interface XLService {
        @Multipart
        @POST("/users/sign_in")
        public void signIn(@Part("provider") String provider, @Part("uid") String uid, @Part("access_token") String access_token,
                           @Part("refresh_token") String refresh_token, @Part("expired_at") String expired_at,
                           @Part("avatar") String avatar, @Part("gender") String gender,
                           @Part("city") String city, @Part("nickname") String nickname,
                           @Part("description") String description,Callback<LoginResponse> callback);

//        @GET("/comic_lists/1")
//        public void getComicLists(@Query("offset") int offset, @Query("limit") int limit, Callback<FeedResponse> callback);

        //获取预告列表
        @GET("/previews")
        public void getPreviews(@Query("page") int page, @Query("per_page") int per_page, Callback<PreviewBean[]> callback);

        //获取某人的预告列表
        @GET("/users/{id}/previews")
        public void getUserPreviews(@Path("id") String id, @Query("page") int page, @Query("per_page") int per_page, Callback<PreviewBean[]> callback);

        //发布预告
        @Multipart
        @POST("/previews")
        public void postPreviews(@Part("name") String name, @Part("start_at") String start_at, @Part("cover") String cover, Callback<PreviewBean> callback);

        //获取直播列表
        @GET("/rooms")
        public void getFeedList(@Query("type") String type, @Query("page") int page, @Query("per_page") int per_page, Callback<List<RoomBean>> callback);


        //获取直播列表
        @GET("/users/{id}/rooms")
        public void getUserRooms(@Path("id") String id, @Query("page") int page, @Query("per_page") int per_page, Callback<RoomBean[]> callback);

        //发布直播
        @Multipart
        @POST("/rooms")
        public void postZhibo(@Part("name") String name, @Part("cover") String cover, @Part("tencent_room_id") String tencent_room_id, Callback<RoomBean> callback);

        /**
         * 更新直播信息
         * status #必填，online 正在直播 offline 直播结束 的状态更新
         */

        @Multipart
        @PUT("/rooms/{id}")
        public void putFeedInfo(@Path("id") String id, @Part("name") String name, @Part("description") String description, @Part("cover") String cover, @Part("duration") int duration,
                                @Part("end_at") String end_at, @Part("tencent_group_id") String tencent_group_id,
                                @Part("tencent_file_id") String tencent_file_id, @Part("status") String status, Callback<RoomBean> callback);

        //直播保存结束后
        @Multipart
        @PUT("/rooms/{id}")
        public void putFeedInfo(@Path("id") String id, @Part("duration") int duration, @Part("end_at") String end_at,
                                @Part("tencent_file_id") String tencent_file_id, @Part("status") String status, Callback<RoomBean> callback);

        //push 流数据
        @Multipart
        @PUT("/rooms/{id}")
        public void putFeedInfo(@Path("id") String id, @Part("tencent_channel_id") String tencent_channel_id,
                                @Part("tencent_channel_url") String tencent_channel_url, @Part("status") String status, Callback<RoomBean> callback);

        //结束后
        @Multipart
        @PUT("/rooms/{id}")
        public void putFeedInfo(@Path("id") String id, @Part("status") String status, Callback<RoomBean> callback);


        @GET("/rooms/{id}")
        public void getFeedInfo(@Path("id") String id, Callback<RoomBean> callback);

        /**
         * 推荐关注
         * type:recommend 推荐用户 hot 人气用户 newest 最新入驻
         */
        @GET("/stars")
        public void getStars(@Query("type") String type, @Query("page") int page, @Query("per_page") int per_page, Callback<ChannelBean[]> callback);

        @GET("/system/notices")
        public void getNotices( @Query("page") int page, @Query("per_page") int per_page, Callback<MsgBean[]> callback);

        @GET("/gifts")
        public void getGifts( Callback<GiftBean[]> callback);


        @GET("/users/{id}")
        public void getUserInfo( @Path("id") String id, Callback<UserBean> callback);

        @GET("/users/{id}/contributions")
        public void getContributions( @Path("id") String id, @Query("page") int page, @Query("per_page") int per_page, Callback<ContributionBean[]> callback);

        @Multipart
        @PUT("/users/{id}")
        public void putUserInfo( @Path("id") String id, @Part("nickname") String nickname, @Part("gender") String gender,
                                 @Part("description") String description, @Part("avatar") String avatar,
                                 @Part("address") String address, Callback<UserBean> callback);

        @Multipart
        @PUT("/users/{id}")
        public void putUserInfoNickName( @Path("id") String id, @Part("nickname") String nickname, Callback<UserBean> callback);

        @Multipart
        @PUT("/users/{id}")
        public void putUserInfoGender( @Path("id") String id, @Part("gender") String gender, Callback<UserBean> callback);

        @Multipart
        @PUT("/users/{id}")
        public void putUserInfoDescription( @Path("id") String id, @Part("description") String description, Callback<UserBean> callback);

        @Multipart
        @PUT("/users/{id}")
        public void putUserInfoAvatar( @Path("id") String id, @Part("avatar") String avatar, Callback<UserBean> callback);

        @Multipart
        @PUT("/users/{id}")
        public void putUserInfoAddress( @Path("id") String id, @Part("address") String address, Callback<UserBean> callback);

        @Multipart
        @POST("/rooms/{id}/praises")
        public void postPraises( @Path("id") String id, @Part("status") String status,  Callback<NullResponse> callback);

        @Multipart
        @POST("/rooms/{id}/gifts")
        public void sendGift(@Path("id") String id, @Part("gift_id") String gift_id, @Part("quantity") String quantity,Callback<NullResponse> callback);


        /**
         *  房间发消息，弹幕
         */
        @Multipart
        @POST("/rooms/{id}/comments")
        public void sendRoomComments(@Path("id") String id, @Part("message") String message, @Part("is_barrage") boolean is_barrage, Callback<NullResponse> callback);

        /**
         * @param id
         * @param eq online offline
         */
        @GET("/rooms/{id}/users")
        public void getRoomUsers(@Path("id") String id, @Query("q[status_eq]") String eq, Callback<UserBean[]> callback);

        /**
         * 获取房间评论
         * @param id
         * @param callback
         */
        @GET("/rooms/{id}/comments")
        public void getRoomComments(@Path("id") String id, Callback<CommentBean[]> callback);

        @Multipart
        @POST("/rooms/{id}/users")
        public void enterRoom(@Path("id") String id, @Part("name") String name, Callback<NullResponse> callback);

        @DELETE("/rooms/{id}/users/cancel")
        public void exitRoom( @Path("id") String id, Callback<NullResponse> callback);

        @Multipart
        @POST("/users/apply")
        public void apply(@Part("invite_code") String invite_code, Callback<NullResponse> callback);

        //获取粉丝列表
        @GET("/users/{id}/followers")
        public void getFollowers(@Path("id") String id, @Query("page") int page, @Query("per_page") int per_page, Callback<UserBean[]> callback);

        //关注动作
        @Multipart
        @POST("/users/{id}/followings")
        public void following(@Path("id") String id, @Part("name") String name, Callback<NullResponse> callback);

        //取消关注动作
        @DELETE("/users/{id}/followings/cancel")
        public void delFollowing(@Path("id") String id, Callback<NullResponse> callback);

//        //批量动作
//        @POST("/users/followings")
//        public void bratchFollowing(@Body String user_ids, Callback<NullResponse> callback);
//
//        //批量取消关注
//        @POST("/users/followings/cancel")
//        public void bratchCancelFollowing(@Body String user_ids, Callback<NullResponse> callback);

        //批量动作
        @POST("/users/followings")
        public void bratchFollowing(@Body BatchCancelRequestBody rb, Callback<NullResponse> callback);

        //批量取消关注
        @POST("/users/followings/cancel")
        public void bratchCancelFollowing(@Body BatchCancelRequestBody rb, Callback<NullResponse> callback);

        //预约
        @Multipart
        @POST("/appointments")
        public void appointments(@Part("preview_id") String preview_id, Callback<PreviewResponse> callback);

        @Multipart
        @POST("/umeng/mobile_devices")
        public void putMobileDevice(@Part("type") String type, @Part("device_token") String device_token, Callback<NullResponse> callback);


        @DELETE("/appointments/{preview_id}/preview ")
        public void delAppointments(@Path("preview_id") String preview_id, Callback<PreviewResponse> callback);

        @GET("/users/{id}/appointments")
        public void getAppointments(@Path("id") String id, @Query("page") int page, @Query("per_page") int per_page, Callback<PreviewBean[]> callback);

        @GET("/users/{id}/followings")
        public void getFollowings(@Path("id") String id, @Query("page") int page, @Query("per_page") int per_page, Callback<UserBean[]> callback);

        @GET("/system/config")
        public void getConfig( Callback<ConfigResponse> callback);

        //获取用户设置
        @GET("/users/settings")
        public void getSetting( Callback<UserSettingResponse> callback);

        //修改用户设置
        @Multipart
        @PUT("/users/settings")
        public void putSetting(@Part("follow_notice") boolean follow_notice, @Part("system_msg_notice") boolean system_msg_notice, Callback<UserSettingResponse> callback);

        /**
         * key 图片路径
         * @param key
         * @param callback
         */
        @Multipart
        @POST("/qiniu/uptoken")
        public void upToken(@Part("key") String key, Callback<UpTokenResponse> callback);

        @Multipart
        @POST("/rooms/{id}/online")
        public void postHeartClick(@Path("id") String id, @Part("status") String status, Callback<NullResponse> callback);

        //获取用户账户信息
        @GET("/users/account")
        public void getAccountInfo( Callback<AccountBean> callback);

        //提现
        @Multipart
        @POST("/accounts/withdraw")
        public void withDraw(@Part("amount") String amount, Callback<NullResponse> callback);

        //支付
        @Multipart
        @POST("/accounts/pay")
        public void pay(@Part("product_id") String product_id, @Part("channel") String channel,@Part("amount") int amount, @Part("price") float price, Callback<NullResponse> callback);

        @Multipart
        @POST("/accounts/bind_weixin")
        public void bindWeixin(@Part("open_id") String open_id, Callback<NullResponse> callback);

        //获取最新版本升级地址
        @GET("/system/upgrade")
        public void checkVersion(Callback<CheckVersionResponse> callback);



//        @GET("/comics/{comic_id}")
//        public void getComicDetail(@Path("comic_id") long id, Callback<ComicDetailResponse> callback);


//        @GET("/{action}")
//        public void getMixTopics(@Path("action") String action, @Query("offset") int offset, Callback<TopicListResponse> callback);
//
//
//        @POST("/comics/{comic_id}/like")
//        public void likeComic(@Path("comic_id") long id, Callback<EmptyDataResponse> callback);
//
//        @DELETE("/comics/{comic_id}/like")
//        public void disLikeComic(@Path("comic_id") long id, Callback<EmptyDataResponse> callback);
//
//        @Multipart
//        @POST("/comics/{comic_id}/rec")
//        public void recComic(@Path("comic_id") long id, Callback<EmptyDataResponse> callback);

    }

    //指定Json解析格式
    class ItemTypeAdapterFactory implements TypeAdapterFactory {
        public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
            final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
            final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
            return new TypeAdapter<T>() {
                public void write(JsonWriter out, T value) throws IOException {
                    delegate.write(out, value);
                }

                public T read(JsonReader in) throws IOException {
                    JsonElement jsonElement = elementAdapter.read(in);
                    if (jsonElement.isJsonObject()) {
                        JsonObject jsonObject = jsonElement.getAsJsonObject();
                        if (jsonObject.has("data") && (jsonObject.get("data").isJsonObject() ||  jsonObject.get("data").isJsonArray())) {
                            jsonElement = jsonObject.get("data");
                        }
                    }
                    return delegate.fromJsonTree(jsonElement);
                }
            }.nullSafe();
        }
    }

    class XLRequestInterceptor implements RequestInterceptor {
        String token;
        String version;

        public XLRequestInterceptor(String token,  String version) {
            this.token = token;
            this.version = version;
        }

        @Override
        public void intercept(RequestFacade request) {
            if (token != null) {
                request.addHeader("token", token);
            }
            if (version != null) {
                request.addHeader("version", version);
            }
        }

    }
}
